/*
  S.M.A.C.K - An operating system kernel
  Copyright (C) 2010,2011 Mattias Holm and Kristian Rietveld
  For licensing and a full list of authors of the kernel, see the files
  COPYING and AUTHORS.
*/

#ifndef KERNEL__VFS_FAT32_H
#define KERNEL__VFS_FAT32_H

/*
  Types and defines used for accessing FAT32 file systems

  Note, that the FAT32 fs will be little endian. Take care in the implementation.
*/
#include <stdint.h>

#define FAT32_FREE    0x00000000
#define FAT32_RESV    0x00000001
#define FAT32_USED_LO 0x00000002
#define FAT32_USED_HI 0x0fffffef
#define FAT32_BAD     0x0ffffff7
#define FAT32_LAST_LO 0x0ffffff8
#define FAT32_LAST_HI 0x0fffffff

#define PART_TYPE_FAT32A 0x0b
#define PART_TYPE_FAT32B 0x0c

typedef struct {
  uint8_t bootflag;
  uint8_t chs_begin[3];
  uint8_t type_code;
  uint8_t chs_end[3];
  uint32_t lba_begin; // Where the fs is located on disk
  uint32_t num_sectors;
} __attribute__((__packed__)) partition_entry_t;

typedef struct {
  uint8_t boot_code[446];
  partition_entry_t part_entry[4];
  uint16_t magic;
} __attribute__((__packed__)) mbr_t;


typedef struct {
  uint8_t jmp[3];
  uint8_t oem[8];
  uint16_t sector_size;
  uint8_t sec_per_cluster;
  uint16_t reserved_sector_count;
  uint8_t n_fats;
  uint16_t max_root_entries;
  uint16_t tot_sectors16;
  uint8_t media_desc;
  uint16_t sectors_per_fat;
  uint16_t sectors_per_track;
  uint16_t n_heads;
  uint32_t hidden_sectors;
  uint32_t tot_sectors32;
} __attribute__((__packed__)) fat_volume_id_t;

typedef struct {
  uint32_t sectors_per_fat;
  uint16_t fat_flags;
  uint16_t version;
  uint32_t root_dir_cluster;
  uint16_t fs_info_sector;
  uint16_t boot_copy_sector;
  uint8_t reserved0[12];
  uint8_t phys_drive_num;
  uint8_t reserved1;
  uint8_t ext_boot_signature;
  uint32_t id;
  uint8_t volume_label[11];
  uint8_t fat_fs_type[8];
  uint8_t os_boot_code[420];
  uint16_t boot_sector_signature;
} __attribute__((__packed__)) fat32_volume_id_ext_t;

typedef struct {
  fat_volume_id_t volume_id;
  fat32_volume_id_ext_t volume_id_ext;
} __attribute__((__packed__)) fat32_volume_id_t;



typedef struct {
  uint32_t fs_info_signature0;
  uint8_t reserved0[480];
  uint32_t fs_info_signature1;
  uint32_t n_free_clusters;
  uint32_t n_last_cluster;
  uint8_t reserved1[14];
  uint16_t fs_info_signature2;
} __attribute__((__packed__)) fs_info_sector_t;


#define FAT_RO           0x01
#define FAT_HIDDEN       0x02
#define FAT_SYSTEM       0x04
#define FAT_VOLUME_LABEL 0x08
#define FAT_SUBDIR       0x10
#define FAT_ARCHIVE      0x20
#define FAT_DEVICE       0x40
#define FAT_UNUSED       0x80
#define FAT_LONGNAME     0x0f

typedef struct {
  uint8_t filename[8];
  uint8_t fileext[3];
  uint8_t attribs;
  uint8_t reserved0;
  uint8_t create_time_10ms;
  uint16_t create_time_hms;
  uint16_t create_date;
  uint16_t last_access_date;
  uint16_t ea_index; // High 2 bytes of cluster number
  uint16_t last_modified_time;
  uint16_t last_modified_date;
  uint16_t start_of_file;
  uint32_t file_size;
} __attribute__((__packed__)) fat_dirent_t;

#endif /* !KERNEL__VFS_FAT32_H */
